<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>VUE3</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <style>
        .flex{
            display: flex;
            position: relative;
        }
        .left{
            width: 240px;
            position: absolute;
            left: 0;
            top: 0;
            height: auto;
        }
        .left p{
            font-size: 14px;
            padding: 0;
            margin: 0;
        }
        .left .tip{
            font-size: 20;
            font-weight: bold;
        }
        .right{
            flex: 1;
            padding-left: 250px;
            height: 100vh;
            overflow: scroll;
        }
        .right p{
            padding: 0;
            margin: 0;
            text-indent: 4em;
            line-height: 30px;
        }
        .right .indent6{
            text-indent: 6em;
        }
        .right .title{
            font-weight: bold;
        }
        .title{
            color: #a0cfff;
        }
        h3{
            background-color: #ccc;
        }
        h4{
            text-indent: 2em;
            padding: 0;
            margin: 0;
            color: #409eff;
        }
        ul,li{
            list-style: none;
        }
        a{
            text-decoration: none;
        }
    </style>
</head>
<body>
    <div id="app" class="flex">
        <div class="left">
            <p>参考：
                <a target="_blank" href="http://blog.csdn.net/qq_38689395/article/details/122260297">vue3面试题</a> 
            </p>
            <ul>
                <li v-for="menu in menus">
                    <p class="tip">{{menu.name}}</p>
                    <template v-if="menu.children">
                        <p style="padding-left:20px" v-for="title in menu.children" :key="title.id">
                            <a :href=`#${title.id}`>{{title.name}}</a>
                        </p>
                    </template>
                </li>
            </ul>
        </div>
        <div class="right">
            <h3>CSS</h3>
            <div>
                <div id="css1">
                    <h4>vue2和vue3优势</h4>
                    <p>性能更好
                        体积更小
                        更好的 TS 支持
                        更好的代码组织
                        更好的逻辑抽离
                        更多新功能
                    </p>
                </div>
                <div id="css2">
                    <h4>生命周期</h4>
                    <p>onBeforeMount、onMounted、onBeforeUpdate、onUpdated、onBeforeUnmount、onUnmounted</p>
                </div>
                <div id="css3">
                    <h4>composition VS options</h4>
                    <p>composition API 优点：</p>
                    <p class="indent6">
                        更好的代码组织
                        更好的逻辑复用
                        更好的类型推导</p>
                </div>
                <div id="css4">
                    <h4>如何理解 ref toRef 和 toRefs</h4>
                    <p class="title">ref</p>
                    <p class="indent6">生成值类型的响应式数据、可用于模板和 reactive、通过 .value 修改值</p>
                    <p class="title">toRef</p>
                    <p class="indent6">针对一个响应式对象（reactive 封装）的 prop、创建一个 ref，具有响应式、两者保持引用关系;toRef 如果用于普通对象（非响应式对象），产出的结果不具备响应式</p>
                    <p class="title">toRefs</p>
                    <p class="indent6">将响应式对象（reactive 封装）转换为普通对象、对象的每个 prop 都是对应的 ref、两者保持引用关系；注意：直接解构 reactive 返回的 state ，页面能显示内容，但内容不是响应式的</p>
                    <p class="title">ref toRef 和 toRefs的最佳使用方式</p>
                    <p>用 reactive 做对象的响应式，用 ref 做值类型响应式、setup 中返回 toRefs(state) 或者 toRef(state, 'xxx')、ref 的变量命名都用 xxxRef、合成函数返回响应式对象，使用 toRefs</p>
                </div>
                <div id="css5">
                    <h4>reactive</h4>
                    <p>reactive 是 Vue3 中提供的实现响应式数据的方法。
                        在 Vue2 中响应式数据是通过 defineProperty 来实现的，
                        在 Vue3 中响应式数据是通过 ES6 的 Proxy来实现的。
                        <br/>
                        reactive 参数必须是对象 (json / arr)、 如果给 reactive 传递了其它对象、默认情况下，修改对象无法实现界面的数据绑定更新。如果需要更新，需要进行重新赋值。(即不允许直接操作数据，需要放个新的数据来替代原数据)
                        #### 在 reactive 使用基本类型参数
                        <br/>
                        基本类型(数字、字符串、布尔值)在 reactive 中无法被创建成 proxy 对象，也就无法实现监听。</p>
                </div>
                <div id="css6">
                    <h4>Vue3 升级了哪些重要功能</h4>
                    <p>createApp、emits 属性、多事件处理、Fragment、移除 .sync换成v-model、异步组件、移除 filter、Teleport（把组件放到外面，vue2只能操作dom）、Suspense</p>
                    <p class="title">Composition API</p>
                    <p class="indent6">reactive、ref 相关、readonly、watch 和 watchEffect、setup、生命周期钩子函数</p>
                </div>
                <div id="css7">
                    <h4>Vue3 如何实现响应式</h4>
                    <p>Object.defineProperty 的缺点：深度监听需要一次性递归、无法监听新增属性/删除属性（Vue.set、Vue.delete）、无法原生监听数组，需要特殊处理</p>
                    <p>Proxy 实现响应式优点：深度监听，性能更好、可监听新增/删除属性、可监听数组变化</p>
                    <p>性能是如何提升的：Proxy 实现不是一次性监听的，这里深度监听是在 get 中处理的，什么时候用到什么时候处理（惰性）。而 Object.defineProperty 实现是在一开始就进行处理，一次性全部处理完成</p>
                </div>
                <div id="css8">
                    <h4>watch 和 watchEffect 的区别</h4>
                    <p>1、两者都可监听 data 属性变化</p>
                    <p>2、watch 需要明确监听哪个属性：默认是惰性执行，监听源可以是一个具有返回值的 getter 函数，也可以直接是一个 ref</p>
                    <p>watchEffect 会根据其中的属性，自动监听其变化</p>
                </div>
                <div id="css9">
                    <h4>setup 中如何获取组件实例</h4>
                    <p>在 setup 和其他 Composition API(组合式 API) 中没有 this;可通过 getCurrentInstance 获取当前实例;若用 Options API(选项式 API) 可照常使用 this</p>
                </div>
                <div id="css10">
                    <h4>Vue3 为何比 Vue2 快</h4>
                    <p class="title">1、PatchFlag（标记）</p>
                    <p class="indent6">编译模板时，动态节点做标记；标记，分为不同的类型，如：TEXT、PROPS；diff 算法时，可以区分静态节点，以及不同类型的动态节点；Vue2 没有区分静态节点和动态节点；Vue3 新增静态标记 patchFlag 与上次虚拟节点比较时，只比较有 patchFlag 的节点</p>
                    <p class="title">2、hoistStatic（静态提升）</p>
                    <p class="indent6">将静态节点的定义，提升到父作用域，缓存起来;多个相邻静态节点，会被合并起来；典型的拿空间换时间的优化策略；Vue2 无论元素是否参与更新，每次都会重新创建然后再渲染。Vue3 对于不参与更新的元素，做静态提升，只会被创建一次，在渲染时直接复用即可</p>
                    <p class="title">cacheHandler（缓存事件）</p>
                    <p class="indent6">Vue2 绑定事件每次触发都要重新生成全新 Function 去更新。Vue3 提供事件缓存对象，当开启 cacheHandler 会自动生成一个内联函数，同时生成一个静态节点，当事件再次触发时，只需从缓存中调用即可</p>
                    <p class="title">SSR 渲染</p>
                    <p class="indent6">静态节点直接输出，直接绕过 vdom，当做字符串推进 buffer 里；动态节点，还是需要动态渲染</p>
                    <p class="title">tree shaking（按需编译）</p>
                    <p class="indent6">编译时，根据不同的情况，引入不同的 API;可以静态分析模块依赖并删除未使用的导出相关的代码</p>
                </div>
                <div id="css11">
                    <h4>Vite</h4>
                    <p>优势：开发环境使用 ES6 Module，无需打包——非常快；生成环境使用 rollup，并不会快很多</p>
                    <p class="title">Commonjs 的特性如下：</p>
                    <p class="indent6">1、CommonJS 模块由 JS 运行时实现。</p>
                    <p class="indent6">2、CommonJs 是单个值导出，本质上导出的就是 exports 属性。</p>
                    <p class="indent6">3、CommonJS 是可以动态加载的，对每一个加载都存在缓存，可以有效的解决循环引用问题。</p>
                    <p class="indent6">4、CommonJS 模块同步加载并执行模块文件。</p>
                    <p class="title">ES6 Module：</p>
                    <p class="indent6">1、ES6 Module 静态的，不能放在块级作用域内，代码发生在编译时。</p>
                    <p class="indent6">2、ES6 Module 的值是动态绑定的，可以通过导出方法修改，可以直接访问修改结果。</p>
                    <p class="indent6">3、ES6 Module 可以导出多个属性和方法，可以单个导入导出，混合导入导出。</p>
                    <p class="indent6">4、ES6 模块提前加载并执行模块文件。</p>
                    <p class="indent6">5、ES6 Module 导入模块在严格模式下。</p>
                    <p class="indent6">6、ES6 Module 的特性可以很容易实现 Tree Shaking 和 Code Splitting。</p>
                </div>
                <div id="css12">
                    <h4>传值</h4>
                    <p>props / emits 父子组件通信:--PS:const emit:any = defineEmits();</p>
                    <p>provide / inject 多层嵌套组件通信</p>
                    <p>$attrs 包含了父作用域中不作为组件 props 或 emits 的 attribute 绑定和事件。当一个组件没有声明任何 prop 时，这里会包含所有父作用域的绑定，并且可以通过 v-bind="$attrs" 传入内部组件——这在创建高阶的组件时会非常有用。</p>
                    <p>$parent 这是父实例，如果当前实例有的话。简单粗暴拿着实例各种用。</p>
                    <p>$refs 一个对象，持有注册过ref的所有 DOM 元素和组件实例。父组件使用其可以轻易的获取子组件，并各种使用。</p>
                    <p>eventBus 事件总线vue3不支持了: 可以使用一些外部第三方库，例如 mitt 或 tiny-emitter</p>
                    <p>全局状态管理，比如 Vuex</p>
                </div>
                <div id="css13">
                    <h4>ref和reactive区别</h4>
                    <p>1、ref是把值类型添加一层包装，使其变成响应式的引用类型的值。
                        <br/>
                        2、reactive 则是引用类型的值变成响应式的值。</p>
                    <p>两者的区别只是在于是否需要添加一层引用包装，对于对象而言，添加一层包装后会被reactive处理为深层的响应式对象，在调用unref后就能看到其实对象是一个Reactive对象。</p>
                </div>
                <div id="css14">
                    <h4>Vue3中的响应式原理</h4>
                    <p>1、通过Proxy（代理）： 拦截对象中任意属性的变化，包括：属性值的读写，属性的增加，属性的删除等。
                        <br/>
                        2、通过Reffect（反射）： 对源对象的属性进行操作</p>
                </div>
                <div id="css15">
                    <h4>Hook</h4>
                    <p class="title">使用规则:只能在setup函数里面使用。</p>
                    <p class="title">常用hook：</p>
                    <p class="indent6">ref:接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property，指向该内部值。</p>
                    <p class="indent6">reactive:用来定义引用类型的响应式数据。注意，不能用来定义基本数据类型的响应式数据，不然会报错。定义的对象是不能直接使用es6语法解构的，不然就会失去它的响应式，如果硬要解构需要使用toRefs()方法。<br/>
                        使用reactive定义响应式对象，里面的属性是ref定义的话可以直接赋值而不需要再.value，并且数据的修改是响应式的。</p>
                    <p class="indent6">computed:是计算属性，意思就是会缓存值，只有当依赖属性发生变化的时候才会重新计算。</p>
                    <p class="indent6">watchEffect:立即执行传入的一个函数，同时响应式追踪其依赖，并在其依赖变更时重新运行该函数.怎么理解这句话呢？就是它会自动收集依赖，不需要手动传入依赖。当里面用到的数据发生变化时就会自动触发watchEffect。并且watchEffect 会先执行一次用来自动收集依赖。而且watchEffect 无法获取到变化前的值，只能获取变化后的值。</p>
                    <p class="indent6">watch: 需要侦听特定的数据源，并在单独的回调函数中执行副作用。默认情况下，它也是惰性的——即回调仅在侦听源发生变化时被调用。</p>
                    <p class="title">hooks帮助我们解决了什么问题呢？</p>
                    <p class="indent6">1、高内聚低耦合，充分解耦业务代码的复杂性，可读性更高</p>
                    <p class="indent6">2、业务代码结构清晰且明了</p>
                    <p class="indent6">3、可复用性更高</p>
                    <p class="indent6">4、数据剥离，调用两次hooks，代表着两份完全独立的数据，减少数据污染的可能性</p>
                    <p class="indent6">5、使用方便，难度低，充分代替mixin，变量来源不明确（隐式传入），不利于阅读，使代码变得难以维护</p>
                    <p class="indent6">6、多个 mixins 的生命周期会融合到一起运行，但是同名属性、同名方法无法融合，可能会导致冲突</p>
                </div>
            </div>
        </div>
    </div>
</body>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            menus: [
                {
                    name:'vue3',
                    children:[
                        {
                            id:'css1',
                            name:'vue2和vue3区别'
                        },
                        {
                            id:'css2',
                            name:'生命周期'
                        },
                        {
                            id:'css3',
                            name:'composition(组合式) VS options(选项式)'
                        },
                        {
                            id:'css4',
                            name:'如何理解 ref toRef 和 toRefs'
                        },
                        {
                            id:'css5',
                            name:'reactive'
                        },
                        {
                            id:'css6',
                            name:'Vue3 升级了哪些重要功能'
                        },
                        {
                            id:'css7',
                            name:'Vue3 如何实现响应式'
                        },
                        {
                            id:'css8',
                            name:'watch 和 watchEffect 的区别'
                        },
                        {
                            id:'css9',
                            name:'setup 中如何获取组件实例'
                        },
                        {
                            id:'css10',
                            name:'Vue3 为何比 Vue2 快'
                        },
                        {
                            id:'css11',
                            name:'Vite'
                        },
                        {
                            id:'css12',
                            name:'组件传值'
                        },
                        {
                            id:'css13',
                            name:'ref和reactive区别'
                        },
                        {
                            id:'css14',
                            name:'Vue3中的响应式原理'
                        },
                        {
                            id:'css15',
                            name:'Hook'
                        }
                    ]
                },
            ],
        },
    })
</script>
</html>